package com.cqz.mylibrary;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.graphics.PointF;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.SweepGradient;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2016/12/13.
 */

public class CircleSeekBar extends View
{
    /**分段颜色*/
    private static final int[] SECTION_COLORS = {Color.parseColor("#94e409"),Color.parseColor("#92df0c")};
    //弧度转角度
    private static final double RADIAN = 180 / Math.PI;
    //半径
    private int mRadius;
    //画弧的笔
    private Paint mArcPaint;
    //弧尽头的小圆点
    private Paint mPointPaint;
    //小圆点的X坐标
    private float mPointX;
    //小圆点的Y坐标
    private float mPointY;
    //小圆点的半径
    private float mPointRadius;
    //小圆点的颜色
    private int mPointColor;
    //弧线宽度
    private float mArcWidth;
    //弧线颜色
    private int mArcColor;
    //起始角度,绘制的时候会用到
    private int mStartAngle;

    private int mArcBgColor = Color.WHITE;

    //初始角度
    private int mCalculateStartAngle;
    //最大角度
    private int mMaxAngle;
    //当前的角度
    private float mCurrentAngle = 0;
    //当前进度值
    private int mCurrentProgerss;
    //最大进度值
    private int mMaxProgress;

    private OnProgressChangeListener mListener;

    public CircleSeekBar(Context context)
    {
        this(context, null);
    }

    public CircleSeekBar(Context context, AttributeSet attrs)
    {
        this(context, attrs, 0);
    }

    public CircleSeekBar(Context context, AttributeSet attrs, int defStyleAttr)
    {
        super(context, attrs, defStyleAttr);
        initView(attrs, defStyleAttr);
    }

    private void initView(AttributeSet attrs, int defStyleAttr)
    {


        initAttrs(attrs, defStyleAttr);
        initPaint();
    }

    private void initAttrs(AttributeSet attrs, int defStyleAttr)
    {
        TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.CircleSeekBar, defStyleAttr, 0);
        mArcWidth = a.getDimension(R.styleable.CircleSeekBar_arc_width, 20);
        mArcColor = a.getColor(R.styleable.CircleSeekBar_arc_color, Color.BLUE);
        mArcBgColor = a.getColor(R.styleable.CircleSeekBar_arcBg_color, Color.WHITE);
        mPointRadius = a.getDimension(R.styleable.CircleSeekBar_point_radius, mArcWidth / 2);
        mPointColor = a.getColor(R.styleable.CircleSeekBar_point_color, Color.WHITE);
        mStartAngle = a.getInt(R.styleable.CircleSeekBar_start_angle, 135);
        mMaxAngle = a.getInt(R.styleable.CircleSeekBar_max_angle, 270);
        mCurrentProgerss = a.getInt(R.styleable.CircleSeekBar_current_progress, 0);
        mMaxProgress = a.getInt(R.styleable.CircleSeekBar_max_progress, 100);
        a.recycle();
        //处理角度偏差
        mCalculateStartAngle = mStartAngle % 90;
    }
    Paint mArcBgPaint;
    private void initPaint()
    {
        mArcBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
//        LinearGradient mShader=new LinearGradient(0,200,200,200, SECTION_COLORS[0], SECTION_COLORS[1], Shader.TileMode.MIRROR);
        Shader mShader = new SweepGradient(getWidth()/2, getHeight()/2, SECTION_COLORS, null);

//        mArcBgPaint.setColor(mArcBgColor);
        mArcBgPaint.setShader(mShader);
        mArcBgPaint.setStrokeWidth(mArcWidth);
        mArcBgPaint.setStyle(Paint.Style.STROKE);
        mArcBgPaint.setStrokeCap(Paint.Cap.ROUND);
        //初始化弧形的笔
        mArcPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mArcPaint.setColor(mArcColor);
        mArcPaint.setStrokeWidth(mArcWidth);
        mArcPaint.setStyle(Paint.Style.STROKE);
        mArcPaint.setStrokeCap(Paint.Cap.ROUND);
        //初始化小圆点的笔
        mPointPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPointPaint.setColor(mPointColor);
        mPointPaint.setStyle(Paint.Style.FILL);

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = measureWidth(widthMeasureSpec);
        int height = measureHeight(heightMeasureSpec);
//        //取宽度和高度的最小值
//        int diameter=Math.min(width,height);
        setMeasuredDimension(width, height);
    }

    private int measureWidth(int widthMeasureSpec)
    {
        int specSize = MeasureSpec.getSize(widthMeasureSpec);
        int specMode = MeasureSpec.getMode(widthMeasureSpec);
        int result;
        if (specMode == MeasureSpec.EXACTLY)
        {
            result = specSize;
        } else
        {
            result = 30;
            if (specMode == MeasureSpec.AT_MOST)
            {
                result = Math.min(result, specSize);
            }
        }
        return result;
    }

    private int measureHeight(int heightMeasureSpec)
    {
        return measureWidth(heightMeasureSpec);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh)
    {
        super.onSizeChanged(w, h, oldw, oldh);
        mRadius = Math.min(w - getPaddingLeft() - getPaddingRight(), h - getPaddingTop() - getPaddingBottom()) / 2;
        initLineOval();

    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        super.onDraw(canvas);
        RectF reactF_bj = new RectF(getPaddingLeft() + mArcWidth, getPaddingTop() + mArcWidth, getPaddingLeft() + 2 * mRadius - mArcWidth,
                getPaddingTop() + 2 * mRadius - mArcWidth);
        canvas.drawArc(reactF_bj, mStartAngle, mMaxAngle, false, mArcBgPaint);

        for (int i = 0; i < Math.round(mMaxAngle*nGraduationCount/360f); i++) {
            if(i<mLinesList.size()){
                Line line = mLinesList.get(i);
                canvas.drawLine(line.p1.x, line.p1.y, line.p2.x, line.p2.y, mRollDrawPaint);
            }
        }

        RectF reactF = new RectF(getPaddingLeft() + mArcWidth, getPaddingTop() + mArcWidth, getPaddingLeft() + 2 * mRadius - mArcWidth, getPaddingTop() + 2 * mRadius - mArcWidth);
        canvas.drawArc(reactF, mStartAngle, mCurrentAngle, false, mArcPaint);
        if(mCurrentAngle > 0){
            canvas.drawCircle(mPointX, mPointY, mPointRadius, mPointPaint);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        float x = event.getX();
        float y = event.getY();

        switch (event.getAction())
        {
            case MotionEvent.ACTION_DOWN:
                if (!isValid(x, y))
                {
                    return false;
                }
                calculateAngle(x, y);
                calculateProgress();
                break;
            case MotionEvent.ACTION_MOVE:
                calculateAngle(x, y);
                calculateProgress();
                break;
            case MotionEvent.ACTION_UP:
                calculateAngle(x, y);
                //添加粘性效果
                if (mCurrentAngle <= 5)
                {
                    mCurrentAngle = 1;
                }
                calculateProgress();
                break;
        }
        invalidate();
        return true;
    }

    private void calculateAngle(float x, float y)
    {
        float angle;
        //斜边
        double hypotenuse;
        hypotenuse = Math.sqrt(Math.pow(x - mRadius, 2) + Math.pow(y - mRadius, 2));
        double sin = (double) (y - mRadius) / hypotenuse;
        float pointX;
        float pointY;
        boolean isLeft = x - mRadius < 0;
        if (isLeft)
        {
            angle = (float) (90 - Math.asin(sin) * RADIAN);
            //计算小圆点坐标
            pointX = calculatePointX(isLeft, sin);
            pointY = calculatePointY(sin);
            Log.d("c_angle", "left:" + angle);
        } else
        {
            angle = (float) (180 + 90 + Math.asin(sin) * RADIAN);
            //计算小圆点坐标
            pointX = calculatePointX(isLeft, sin);
            pointY = calculatePointY(sin);
            Log.d("c_angle", "right:" + angle);
        }
        if (angle >= mCalculateStartAngle && angle <= mMaxAngle + mCalculateStartAngle)
        {
            mCurrentAngle = Math.round(angle - mCalculateStartAngle);
            Log.d("cur_angle", "mCurrentAngle:" + mCurrentAngle);
            mPointX = pointX;
            mPointY = pointY;
        }
    }

    /**
     * 计算小圆点的X坐标
     *
     * @param isLeft 判断点是否位于弧形的左半部分
     * @param sin    #calculateAngle计算出来的sin值
     * @return 小圆点的X坐标
     */
    private float calculatePointX(boolean isLeft, double sin)
    {
        return isLeft ? (float) (mRadius - (mRadius - mArcWidth) * Math.sqrt(1 - sin * sin)) + getPaddingLeft() :
                (float) (mRadius + (mRadius - mArcWidth) * Math.sqrt(1 - sin * sin)) + getPaddingLeft();
    }

    private float calculatePointY(double sin)
    {
        return (float) (mRadius + (mRadius - mArcWidth) * sin) + getPaddingTop();
    }

    private void calculateProgress()
    {
        mCurrentProgerss = Math.round(mCurrentAngle / mMaxAngle * mMaxProgress);
        if (mListener != null)
        {
            mListener.onProgress(mCurrentProgerss);
        }
    }

    /**
     * 判断点是否在弧形的半径内
     *
     * @param x
     * @param y
     * @return true在   false不在
     */
    private boolean isValid(float x, float y)
    {
        return Math.pow(x - mRadius - getPaddingLeft(), 2) + Math.pow(y - mRadius - getPaddingTop(), 2) <= mRadius * mRadius;
    }

    public void setCurrentProgress(int progress)
    {
        if (progress > mMaxProgress)
        {
            throw new IllegalArgumentException("progress must < mMaxProgress");
        }
        mCurrentProgerss = progress;
        mCurrentAngle = (float) mCurrentProgerss / mMaxProgress * mMaxAngle;
        float angle = mCurrentAngle + mCalculateStartAngle;
        //与calculateAngle方法求sin值相反
        boolean isLeft = angle <= 180;
        if (isLeft)
        {
            mPointX = calculatePointX(isLeft, Math.sin((90 - angle) / RADIAN));
            mPointY = calculatePointY(Math.sin((90 - angle) / RADIAN));
        } else
        {
            mPointX = calculatePointX(isLeft, Math.sin((angle - 180 - 90) / RADIAN));
            mPointY = calculatePointY(Math.sin((angle - 180 - 90) / RADIAN));
        }

        invalidate();
    }

    public void setOnProgressChangeListener(OnProgressChangeListener listener)
    {
        this.mListener = listener;
    }

    public interface OnProgressChangeListener
    {
        void onProgress(int progress);
    }


    private RectF oval2;//临时的内圆
    private RectF oval3;//临时的外圆
    /** 刻度的个数 */
    private int nGraduationCount = 20;
    /** 刻度的宽度 */
    private int mGraduationWidth = 5;
    //进度刻度的画笔
    private Paint mRollDrawPaint;
    /** 所有线的集合 */
    private List<Line> mLinesList = new ArrayList<Line>();
    private float mGraduationSweepAngle = 359.9f;//刻度划过的角度 如果为360度  获取刻度会默认从右边划过
    /**
     * 刻度对象
     */
    class Line{
        PointF p1 = new PointF();
        PointF p2 = new PointF();
    }

    private void initLineOval(){
        Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);//消除锯齿
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(0xBBffffff);
        mPaint.setStrokeWidth(mArcWidth);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mRollDrawPaint = new Paint(mPaint);
        mRollDrawPaint.setStrokeWidth(mGraduationWidth);
        int radiu = (int) ((Math.min(getWidth(), getHeight()))/2-mPaint.getStrokeWidth()) + (int)(mArcWidth);
        oval2 = new RectF();
        oval2.left = getWidth()/2-radiu/6f*5;
        oval2.top = getHeight()/2-radiu/6f*5;
        oval2.right = getWidth()/2+radiu/6f*5;
        oval2.bottom = getHeight()/2+radiu/6f*5;
        oval3 = new RectF();
        oval3.left = getWidth()/2-radiu/10f*8;
        oval3.top = getHeight()/2-radiu/10f*8;
        oval3.right = getWidth()/2+radiu/10f*8;
        oval3.bottom = getHeight()/2+radiu/10f*8;
        mLinesList.clear();

        Path path = new Path();
        Path path1 = new Path();
        //从startAngle开始 绘制180角度
        path.addArc(oval2, mStartAngle, mGraduationSweepAngle);
        path1.addArc(oval3, mStartAngle, mGraduationSweepAngle);

        PathMeasure pm = new PathMeasure(path, false);
        float itemLength = pm.getLength()/(nGraduationCount-1);

        PathMeasure pm1 = new PathMeasure(path1, false);

        float[] pos = new float[2];
        float[] postemp = new float[2];
        for (int i = 0; i < nGraduationCount; i++) {
            pm.getPosTan(itemLength*i, pos , null );
            pm1.getPosTan(itemLength*i/pm.getLength()*pm1.getLength(), postemp , null);
            Line line = new Line();
            line.p1.x = pos[0];
            line.p1.y = pos[1];
            line.p2.x = postemp[0];
            line.p2.y = postemp[1];
            mLinesList.add(line);
        }
    }
}
